package info.batcloud.fanli.core.service.impl;

import info.batcloud.fanli.core.domain.UserSignInfo;
import info.batcloud.fanli.core.entity.User;
import info.batcloud.fanli.core.enums.WalletFlowDetailType;
import info.batcloud.fanli.core.repository.UserRepository;
import info.batcloud.fanli.core.service.SignService;
import info.batcloud.fanli.core.service.SystemSettingService;
import info.batcloud.fanli.core.service.WalletService;
import info.batcloud.fanli.core.settings.IntegralSetting;
import info.batcloud.fanli.core.settings.SignSetting;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class SignServiceImpl implements SignService {

    @Inject
    private UserRepository userRepository;

    @Inject
    private SystemSettingService systemSettingService;

    @Inject
    private WalletService walletService;

    @Override
    public UserSignInfo findByUserId(Long userId) {
        if (userId == null) {
            return new UserSignInfo();
        }

        SignSetting signSetting = systemSettingService.findActiveSetting(SignSetting.class);
        IntegralSetting integralSetting = systemSettingService.findActiveSetting(IntegralSetting.class);
        User user = userRepository.findOne(userId);
        return findSignInfo(user, signSetting, integralSetting);
    }

    public UserSignInfo findSignInfo(User user, SignSetting signSetting, IntegralSetting integralSetting) {
        Date now = new Date();
        UserSignInfo signInfo = new UserSignInfo();
        signInfo.setUserId(user.getId());
        int currentSignTimes;
        boolean signed;
        if (user.getLastSignTime() != null && DateUtils.isSameDay(now, user.getLastSignTime())) {
            signed = true;
            currentSignTimes = user.getContinuousSignTimes();
        } else {
            signed = false;
            if (user.getLastSignTime() == null) {
                currentSignTimes = 0;
            } else if (DateUtils.isSameDay(now, DateUtils.addDays(user.getLastSignTime(), 1))) {
                currentSignTimes = user.getContinuousSignTimes();
            } else {
                currentSignTimes = 0;
                user.setContinuousSignTimes(0);
            }
        }
        int currentContinuousSignTimes = currentSignTimes % signSetting.getSignCycleTimes();
        if (currentContinuousSignTimes == 0 && currentSignTimes != 0) {
            currentContinuousSignTimes = signSetting.getSignCycleTimes();
        }
        signInfo.setContinuousSignTimes(user.getContinuousSignTimes());
        if (signed) {
            signInfo.setCurrentContinuousSignTimes(currentContinuousSignTimes);
            signInfo.setCurrentSignIntegral(integralSetting.getFirstSignIntegral() + (currentContinuousSignTimes - 1) * integralSetting.getIncreaseSignIntegral());
            signInfo.setNextSignIntegral(integralSetting.getFirstSignIntegral() +
                    (currentContinuousSignTimes == signSetting.getSignCycleTimes() ? 0 : currentContinuousSignTimes) * integralSetting.getIncreaseSignIntegral());
        } else {
            signInfo.setCurrentContinuousSignTimes(currentContinuousSignTimes == signSetting.getSignCycleTimes() ? 0 : currentContinuousSignTimes);
            signInfo.setCurrentSignIntegral(integralSetting.getFirstSignIntegral()
                    + (currentContinuousSignTimes == signSetting.getSignCycleTimes() ? 0 : currentContinuousSignTimes) * integralSetting.getIncreaseSignIntegral());
            int nextTimes = (currentContinuousSignTimes + 1) % signSetting.getSignCycleTimes();
            if (nextTimes == 0) {
                nextTimes = signSetting.getSignCycleTimes();
            }
            signInfo.setNextSignIntegral(integralSetting.getFirstSignIntegral() +
                    (nextTimes == signSetting.getSignCycleTimes() ? 0 : nextTimes) * integralSetting.getIncreaseSignIntegral());
        }
        List<UserSignInfo.SignItem> signItemList = new ArrayList<>();
        for (int i = 0; i < signSetting.getSignCycleTimes(); i++) {
            UserSignInfo.SignItem si = new UserSignInfo.SignItem();
            si.setTimes(i + 1);
            si.setSignIntegral(integralSetting.getFirstSignIntegral() + i * integralSetting.getIncreaseSignIntegral());
            signItemList.add(si);
        }
        signInfo.setSigned(signed);
        signInfo.setSignCycleTimes(signSetting.getSignCycleTimes());
        signInfo.setSignItemList(signItemList);
        return signInfo;
    }

    @Override
    @Transactional
    public UserSignInfo userSign(long userId) {
        SignSetting signSetting = systemSettingService.findActiveSetting(SignSetting.class);
        IntegralSetting integralSetting = systemSettingService.findActiveSetting(IntegralSetting.class);
        User user = userRepository.findOne(userId);
        UserSignInfo signInfo = findSignInfo(user, signSetting, integralSetting);
        if (signInfo.isSigned()) {
            return signInfo;
        }
        user.setLastSignTime(new Date());
        user.setContinuousSignTimes(signInfo.getContinuousSignTimes() + 1);
        userRepository.save(user);
        walletService.addIntegral(userId, signInfo.getCurrentSignIntegral(), WalletFlowDetailType.USER_SIGN, null);
        return findSignInfo(user, signSetting, integralSetting);
    }
}
